package com.ecocent.api.helper;

import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;

import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

public class RestTemplateUtil {
	private static final int CONNECT_TIMEOUT = 5000;// 设置超时毫秒数

	private static final int SOCKET_TIMEOUT = 10000;// 设置传输毫秒数

	private static final int REQUESTCONNECT_TIMEOUT = 3000;// 获取请求超时毫秒数
	private static final int CONNECT_ROUTE = 20;// 设置每个路由的基础连接数
	private static final int CONNECT_TOTAL = 200;// 最大连接数

	public static RestTemplate getRestTemplate() throws Exception {
		List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        FormHttpMessageConverter fc = new FormHttpMessageConverter();
        messageConverters.add(fc);
        TextPlainJson2ObjectConverter tp = new TextPlainJson2ObjectConverter();
        messageConverters.add(tp);
		RestTemplate restTemplate = new RestTemplate();
		restTemplate.getMessageConverters().addAll(messageConverters);
		List<HttpMessageConverter<?>> list = restTemplate.getMessageConverters();
		for (Iterator<HttpMessageConverter<?>> iterator = list.iterator(); iterator.hasNext(); ) {
            HttpMessageConverter item = iterator.next();
            if (item instanceof StringHttpMessageConverter) {
                ((StringHttpMessageConverter) item).setDefaultCharset(StandardCharsets.UTF_8);
            } else if (item instanceof FormHttpMessageConverter) {

                ((FormHttpMessageConverter) item).setCharset(StandardCharsets.UTF_8);
               ((FormHttpMessageConverter) item).setMultipartCharset(StandardCharsets.UTF_8);

            }
        }

		restTemplate.setRequestFactory(clientHttpRequestFactory());
		restTemplate.setErrorHandler(new DefaultResponseErrorHandler());
		return restTemplate;
	}

	private static HttpComponentsClientHttpRequestFactory clientHttpRequestFactory() throws Exception {
		try {
			HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
			SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
				@Override
				public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType)
						throws java.security.cert.CertificateException {
					// TODO Auto-generated method stub
					return true;
				}
			}).build();
			httpClientBuilder.setSSLContext(sslContext);
			HostnameVerifier hostnameVerifier = NoopHostnameVerifier.INSTANCE;
			SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
					hostnameVerifier);
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
					.register("http", PlainConnectionSocketFactory.getSocketFactory())
					.register("https", sslConnectionSocketFactory).build();// 注册http和https请求
			PoolingHttpClientConnectionManager poolingHttpClientConnectionManager = new PoolingHttpClientConnectionManager(
					socketFactoryRegistry);// 开始设置连接池
			poolingHttpClientConnectionManager.setMaxTotal(CONNECT_TOTAL); // 最大连接数200
			poolingHttpClientConnectionManager.setDefaultMaxPerRoute(CONNECT_ROUTE); // 同路由并发数20
			httpClientBuilder.setConnectionManager(poolingHttpClientConnectionManager);
			RequestConfig requestConf = RequestConfig.custom().setConnectTimeout(CONNECT_TIMEOUT)
					.setConnectionRequestTimeout(REQUESTCONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
			httpClientBuilder.setRetryHandler(new DefaultHttpRequestRetryHandler(2, true))
					.setDefaultRequestConfig(requestConf);// 重试次数
			HttpClient httpClient = httpClientBuilder.build();
			HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(
					httpClient);// httpClient连接配置
			// clientHttpRequestFactory.setConnectTimeout(20000);// 连接超时
			// clientHttpRequestFactory.setReadTimeout(20000);// 数据读取超时时间
			// clientHttpRequestFactory.setConnectionRequestTimeout(200);//
			// 连接不够用的等待时间
			return clientHttpRequestFactory;
		} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
			throw e;
		}
	}
}
